using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using PowerManage.Entity;
using PowerManage.Entity.Enums;
using PowerManage.Service;
using System.Linq;

namespace PowerManage.API.AuditLog;

/// <summary>
/// 行为过滤器 : 审核日志过滤器
/// </summary>
public class AuditLogActionFilterAttribute : ActionFilterAttribute
{
    /// <summary>
    /// 执行前时间
    /// </summary>
    private DateTime _startTime;

    /// <summary>
    /// 执行后时间
    /// </summary>
    private DateTime _endTime;

    /// <summary>
    /// 审核日志实体
    /// </summary>
    private EleAuditLog _eleAuditLog;

    private readonly IAuditLogService _auditLogService;

    /// <summary>
    /// 日志
    /// </summary>
    private readonly ILogger<AuditLogActionFilterAttribute> _logger;

    private readonly UserManager<EleUser> _userManager;

    /// <summary>
    /// 构造器注入
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="userManager"></param>
    /// <param name="auditLogService"></param>
    public AuditLogActionFilterAttribute(ILogger<AuditLogActionFilterAttribute> logger,
        UserManager<EleUser> userManager, IAuditLogService auditLogService)
    {
        _logger = logger;
        _userManager = userManager;
        _auditLogService = auditLogService;
        _eleAuditLog = new EleAuditLog();
    }

    /// <summary>
    /// 在action方法执行前调用
    /// </summary>
    /// <param name="context"></param>
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        //获取接口的请求参数
        _startTime = DateTime.Now;
        _eleAuditLog = AuditLogHelper.GetRequestAuditLog(context, _userManager);
    }

    /// <summary>
    /// 在action方法执行后调用
    /// </summary>
    /// <param name="context"></param>
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        // 检查是否应该跳过日志记录
        if (ShouldSkipAuditLog(context))
        {
            return;
        }

        //存储接口的返回参数，执行时间，异常则记录信息
        _endTime = DateTime.Now;
        _eleAuditLog.ExecutionDuration = (int)(_endTime - _startTime).TotalMilliseconds;
        _eleAuditLog.ReturnValue = context.Result == null ? String.Empty : JsonConvert.SerializeObject(context.Result);
        if (context.Exception != null)
        {
            _eleAuditLog.AuditLogType = AuditLogType.Exception;
            _eleAuditLog.ExceptionMessage = context.Exception.Message;
            if (_eleAuditLog.ExceptionMessage.Length > 1024)
            {
                _eleAuditLog.ExceptionMessage = _eleAuditLog.ExceptionMessage.Substring(0, 1024);
            }

            _eleAuditLog.Exception = context.Exception.ToString();
            if (_eleAuditLog.Exception.Length > 2000)
            {
                _eleAuditLog.Exception = _eleAuditLog.Exception.Substring(0, 2000);
            }

            //记录文件异常日志
            _logger.LogError(context.Exception, "接口：{0}\r\nMethod：{1}\r\n参数：{2}\r\nIP：{3}\r\n花费时长：{4}",
                _eleAuditLog.ApiUrl, _eleAuditLog.Method, _eleAuditLog.Parameters, _eleAuditLog.ClientIpAddress,
                _eleAuditLog.ExecutionDuration);
        }

        _auditLogService.Add(_eleAuditLog);
    }

    /// <summary>
    /// 判断是否应该跳过审核日志记录
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private bool ShouldSkipAuditLog(ActionExecutedContext context)
    {
        //  检查Action或Controller上是否有AuditLogAttribute且OpenLog为false
        var actionDescriptor =
            context.ActionDescriptor as Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor;
        if (actionDescriptor != null)
        {
            // 1. 检查Action级别的AuditLogAttribute - 最高优先级
            var actionAuditLogAttr = actionDescriptor.MethodInfo.GetCustomAttributes(typeof(AuditLogAttribute), false)
                .FirstOrDefault() as AuditLogAttribute;
            if (actionAuditLogAttr != null)
            {
                // Action级别明确指定，直接返回相反值
                return !actionAuditLogAttr.OpenLog;
            }

            // 2. 检查Controller级别的AuditLogAttribute
            var controllerAuditLogAttr = actionDescriptor.ControllerTypeInfo
                .GetCustomAttributes(typeof(AuditLogAttribute), false)
                .FirstOrDefault() as AuditLogAttribute;
            if (controllerAuditLogAttr != null)
            {
                return !controllerAuditLogAttr.OpenLog;
            }
        }

        // 3. 最后检查URL路径（只在没有明确特性指定时生效）
        var requestPath = context.HttpContext.Request.Path.Value?.ToLower();
        if (!string.IsNullOrEmpty(requestPath) && requestPath.Contains("/api/auditlogs"))
        {
            return true;
        }

        return false; // 默认记录日志
    }
}